import axios, {
    AxiosInstance,
    AxiosRequestConfig,
    AxiosResponse,
    AxiosError,
    InternalAxiosRequestConfig,
    CancelTokenSource,
} from 'axios';
import {message} from 'antd';
import {getToken, clearToken} from './auth';

export interface BaseResponse<T = any> {
    code: number;
    msg: string;
    data: T;
}

// 定义请求配置
export interface RequestConfig extends AxiosRequestConfig {
    // 是否显示错误提示
    showError?: boolean;
    // 是否显示加载提示
    showLoading?: boolean;
    // 是否携带 token
    withToken?: boolean;
    // 自定义错误处理
    customErrorHandler?: (error: AxiosError) => void;
}

// 创建 Axios 实例
const createAxiosInstance = (): AxiosInstance => {
    const instance = axios.create({
        baseURL: import.meta.env.VITE_API_BASE_URL,
        timeout: 15000,
        headers: {
            'Content-Type': 'application/json',
            'X-Requested-With': 'XMLHttpRequest',
        },
    });

    // 请求拦截器
    instance.interceptors.request.use(
        (config: InternalAxiosRequestConfig) => {
            // 添加 token
            const token = getToken();
            if (token) {
                config.headers.Authorization = `Bearer ${token}`;
            }

            // 添加取消令牌
            const source = axios.CancelToken.source();
            config.cancelToken = source.token;

            // 存储取消方法
            (config as any).cancelSource = source;

            return config;
        },
        (error: AxiosError) => {
            return Promise.reject(error);
        },
    );

    // 响应拦截器
    instance.interceptors.response.use(
        (response: AxiosResponse<BaseResponse>) => {
            const {data, config} = response;

            // 处理取消请求
            if (axios.isCancel(data)) {
                return Promise.reject(new Error('请求已取消'));
            }
            // 业务错误处理
            if (data.code !== 200) {
                const showError = (config as RequestConfig).showError ?? true;
                if (showError) {
                    errorMessage(data.code, data);
                }
                return Promise.reject(data);
            }

            return data.data;
        },
        (error: AxiosError) => {
            const config = error.config as RequestConfig;
            const showError = config?.showError ?? true;
            // 取消请求不处理
            if (axios.isCancel(error)) {
                return Promise.reject(error);
            }

            // 自定义错误处理
            if (config?.customErrorHandler) {
                config.customErrorHandler(error);
                return Promise.reject(error);
            }

            // 统一错误处理
            if (showError) {
                handleError(error);
            }

            return Promise.reject(error);
        },
    );

    return instance;
};

// 错误处理函数
const handleError = (error: AxiosError) => {
    if (error.response) {
        const {status, data} = error.response;
        errorMessage(status, data);
    } else if (error.request) {
        message.error('网络错误，请检查网络连接');
    } else {
        message.error('请求失败，请稍后重试');
    }
};

const errorMessage = (status: number, data?: any) => {
    switch (status) {
        case 401:
            message.error('登录已过期，请重新登录');
            clearToken();
            window.location.reload();
            break;
        case 403:
            message.error(data.msg || '没有权限访问该资源');
            break;
        case 404:
            message.error(data.msg || '请求的资源不存在');
            break;
        case 500:
            message.error(data.msg || '服务器内部错误');
            break;
        default:
            message.error(data.msg || data?.message || `请求错误: ${status}`);
    }
};

// 创建实例
const request = createAxiosInstance();

/**
 * 封装 GET 请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 */
export const get = <T = any>(
    url: string,
    params?: any,
    config?: RequestConfig,
): Promise<T> => {
    return request.get(url, {params, ...config});
};

/**
 * 封装 POST 请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 */
export const post = <T = any>(
    url: string,
    data?: any,
    config?: RequestConfig,
): Promise<T> => {
    return request.post(url, data, config);
};

/**
 * 封装 PUT 请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 */
export const put = <T = any>(
    url: string,
    data?: any,
    config?: RequestConfig,
): Promise<T> => {
    return request.put(url, data, config);
};

/**
 * 封装 DELETE 请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 */
export const del = <T = any>(
    url: string,
    params?: any,
    config?: RequestConfig,
): Promise<T> => {
    return request.delete(url, {params, ...config});
};

/**
 * 封装上传请求
 * @param url 请求地址
 * @param file 文件对象
 * @param config 请求配置
 */
export const upload = <T = any>(
    url: string,
    file: File,
    config?: RequestConfig,
): Promise<T> => {
    const formData = new FormData();
    formData.append('file', file);

    return request.post(url, formData, {
        headers: {
            'Content-Type': 'multipart/form-data',
        },
        ...config,
    });
};

export const exportRequest = <T = any>(
    url: string,
    data?: any,
    config?: RequestConfig,
): Promise<T> => {

    return request.post(url, data, {
        responseType: "blob",
        ...config,
    });
};

/**
 * 创建取消令牌
 */
export const createCancelToken = (): CancelTokenSource => {
    return axios.CancelToken.source();
};

export default request;
